package com.my9yu.common.socket.filter.transience;

import java.util.ArrayList;
import java.util.Date;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicLong;

import com.my9yu.common.socket.anno.ResetType;
import com.my9yu.common.socket.core.Command;
import com.my9yu.common.socket.core.Header;
import com.my9yu.common.socket.core.Message;
import com.my9yu.common.socket.filter.session.SessionManager;

/**
 * 断连接SESSION
 * @author Ramon
 */
public class TransientSession {

	/** 身份属性 */
	private static TransientAttribute<Object> ATT_IDENTITY = new TransientAttribute<Object>(SessionManager.IDENTITY);

	private final long sessionId;
	private Date accessTime = new Date();
	private int attachmentState = 0;
	private String ip = "";
	private final ConcurrentMap<String, Object> content;
	private boolean valid = true;
	private Deque<Message> pushMessages;

	// ------

	/**
	 * 销毁SESSION上下文
	 */
	void destory() {
		valid = false;
		content.clear();
		pushMessages.clear();
	}

	public void clearPushMessage(ResetType type, Command command) {
		if (type == ResetType.ALL) {
			pushMessages.clear();
		} else if (type == ResetType.MODULE) {
			Iterator<Message> it = pushMessages.iterator();
			while (it.hasNext()) {
				Message m = it.next();
				if (m.getCommand().getModule() == command.getModule()) {
					it.remove();
				}
			}
		} else if (type == ResetType.COMMAND) {
			Iterator<Message> it = pushMessages.iterator();
			while (it.hasNext()) {
				Message m = it.next();
				if (m.getCommand().equals(command)) {
					it.remove();
				}
			}
		}
	}

	/**
	 * 增加推送消息
	 * @param msg
	 */
	public void addPushMessage(ResetType type, Message msg) {
		Message push = Message.valueOf(
				Header.valueOf(msg.getFormat(), msg.getState(), msg.getSn(), this.sessionId, msg.getCommand()),
				msg.getBody(), msg.getAttachment());

		if (type == ResetType.ALL) {
			pushMessages.clear();
		} else if (type == ResetType.MODULE) {
			Iterator<Message> it = pushMessages.iterator();
			while (it.hasNext()) {
				Message m = it.next();
				if (m.getCommand().getModule() == msg.getCommand().getModule()) {
					it.remove();
				}
			}
		} else if (type == ResetType.COMMAND) {
			Iterator<Message> it = pushMessages.iterator();
			while (it.hasNext()) {
				Message m = it.next();
				if (m.getCommand().equals(msg.getCommand())) {
					it.remove();
				}
			}
		}
		pushMessages.addLast(push);
	}

	// -----

	// TODO 为了兼容旧项目, SESSION 标识使用字符串类型返回
	public String getId() {
		return String.valueOf(sessionId);
	}

	public long getSessionId() {
		return sessionId;
	}

	public Object getIdentity() {
		return ATT_IDENTITY.getValue(this);
	}

	void setIdentity(Object identity) {
		ATT_IDENTITY.setValue(this, identity);
	}

	public Date getAccessTime() {
		return accessTime;
	}

	void setAccessTime(Date accessTime) {
		this.accessTime = accessTime;
	}

	public String getIp() {
		return ip;
	}

	void setIp(String ip) {
		this.ip = ip;
	}

	public int getAttachmentState() {
		return attachmentState;
	}

	public void addAttachmentState(int state) {
		attachmentState |= state;
	}

	public void removeAttachmentState(int state) {
		attachmentState &= ~state;
	}

	public boolean isValid() {
		return valid;
	}

	void setValid(boolean valid) {
		this.valid = valid;
	}

	public List<Message> getPushMessages() {
		ArrayList<Message> result = new ArrayList<Message>(pushMessages.size());
		while (!pushMessages.isEmpty()) {
			result.add(pushMessages.poll());
		}
		return result;
	}

	// --------------------------------------

	public ConcurrentMap<String, Object> getContent() {
		return content;
	}

	// --------

	public TransientSession() {
		this(new ConcurrentHashMap<String, Object>());
	}

	public TransientSession(Object identity) {
		this(identity, new ConcurrentHashMap<String, Object>());
	}

	public TransientSession(Object identity, ConcurrentMap<String, Object> content) {
		// 生成ID
		this.sessionId = nextId();
		this.content = content;
		this.pushMessages = new LinkedBlockingDeque<Message>();
	}

	// ----------

	private static AtomicLong sequence = new AtomicLong();

	/**
	 * 获取下一个序列号
	 * @return
	 */
	private static long nextId() {
		long sn = sequence.getAndIncrement() % 0x00FFFFFFL;
		return sn;
	}

}
